﻿namespace LeadMaster.Controllers
{
  using System.Data.Entity;
  using System.Linq;
  using System.Web.Mvc;
  using LeadMaster.DAL;
  using LeadMaster.ViewModels;
  using System.Collections.Generic;
  using LeadMaster.Models;
  using System.Web;
  using System.IO;
  using LeadMaster.Helpers;
  using System;
  using System.Data.Entity.Core.Objects;
  using System.Text.RegularExpressions;

  [Authorize]
  public class OperationsController : Controller
  {

    private DunsmoreContext db = new DunsmoreContext();

    public ActionResult Index()
    {
      ViewModelSurveys ViewModel = new ViewModelSurveys();

      ViewModel.ListSurveys = db.Surveys.ToList();

      return View(ViewModel.ListSurveys);
    }

    public ActionResult UploadSurveys(Guid callCentreID = new Guid())
    {
      Maintenance.inMaintenance = true;
      int ccID = 0;
      if (callCentreID != Guid.Empty)
      {
        ccID = db.CallCentres.Where(m => m.LogOn == callCentreID).FirstOrDefault().CallCentreID;
        ViewBag.CallCentre = db.CallCentres.Find(ccID).potitle;
        ViewBag.CallCentreID = ccID;
      }
      else
      {
        ViewBag.CallCentreID = new SelectList(db.CallCentres.Where(m => m.active == true), "CallCentreID", "CallCentre");
      }

      ViewBag.SurveyID = new SelectList((from s in db.Surveys
                                         join p in db.PurchaseOrders on s.SurveyID equals p.SurveyID
                                         where (ccID == 0 ? p.CallCentreID == p.CallCentreID : p.CallCentreID == ccID) && p.Visible == true
                                         select new { s.SurveyID, s.Ref }).Distinct(), "SurveyID", "Ref");

      return View();
    }

    [HttpPost]
    public ActionResult UploadSurveys(int CallCentreID, int SurveyID, string hdnFileName, bool CSV)
    {
      string[] lines = System.IO.File.ReadAllLines(HttpRuntime.AppDomainAppPath + @"MiscFiles\" + hdnFileName);
      bool headerline = true;
      int BlockID = 0;
      List<string> ErrHeaders = new List<string>();
      int TotalUploaded = 0;
      int Dups = 0;
      int purchaseOrderID = db.PurchaseOrders.
        Where(m => m.CallCentreID == CallCentreID && m.SurveyID == SurveyID && m.Visible == true)
        .FirstOrDefault()
        .PurchaseOrderID;

      GenericRepository gr = new GenericRepository();
      foreach (string fileLine in lines)
      {
        if (headerline == true)
        {
          // split the header so we know what we are dealing with, and report back on discrepancies
          int indexer = 0;
          List<string> headerCols = fileLine.Split(',').ToList();
          bool isPost = db.PurchaseOrders.Where(m => m.CallCentreID == CallCentreID && m.SurveyID == SurveyID && m.Visible == true && m.DirectPost == true).Count() > 0;
          foreach (var item in headerCols)
          {
            string srchheader = item + (isPost ? "=" : string.Empty);
            if (db.ExportMappings.Where(m => m.SurveyID == SurveyID).Where(m => m.ClientFieldName.Contains(srchheader) || m.ClientField.Contains(srchheader) || m.SurveyContactField.Contains(srchheader)).Count() == 0)
            {
              ErrHeaders.Add(item + " is not recognised in our Export Mapping. Please remove this and try again.");
            }
            indexer++;
            if (db.ExportMappings.Where(m => m.SurveyID == SurveyID && m.ExportOrder == indexer && (m.ClientFieldName.Contains(srchheader) || m.ClientField.Contains(srchheader) || m.SurveyContactField.Contains(srchheader))).Count() == 0)
            {
              ErrHeaders.Add(item + " is out of position. Please see your Export Mapping and compare with the Import file.");
            }
          }
          if (ErrHeaders.Count() > 0)
          {
            // errors
            ViewBag.Errors = ErrHeaders;
            return View("MappingErrors");
          }
        }
        else
        {
          // double quotes are not allowed
          if (fileLine.Contains('"'))
          {
            ErrHeaders.Add("Double quotes in the Import file. Please remove and try again.");
            ViewBag.Errors = ErrHeaders;
            return View("MappingErrors");
          }
          // onto legitimate data
          string[] responses = fileLine.Split(',');
          BlockID = db.LeadStatus.Max(m => m.BlockID);
          BlockID++;
          LeadStatus leadStatus = new LeadStatus();
          leadStatus.LeadFlagsID = 1;
          leadStatus.LeadReasonsID = 1;
          leadStatus.DunsmorePreCheck = true;
          leadStatus.CallCentreID = CallCentreID;
          leadStatus.BlockID = BlockID;
          leadStatus.LeadDate = DateTime.Now.ToString("dd/MM/yyyy");
          db.LeadStatus.Add(leadStatus);
          List<ExportMappings> exportMappings = db.ExportMappings.Where(m => m.SurveyID == SurveyID).OrderBy(m => m.ExportOrder).ToList();
          // Make principle LeadStatus record and upload Contact information
          // && m.SurveyMappingsID != null && m.SurveyContactField!=null
          SurveyContacts surveyContacts = new SurveyContacts();
          foreach (var item in exportMappings.Where(m => m.SurveyContactField != null).ToList())
          {
            if (item.Mandatory == true && responses[Convert.ToInt16(item.ExportOrder) - 1] == string.Empty)
            {
              string strError = item.SurveyContactField ?? item.ClientFieldName;
              strError += " is mandatory, but no value supplied.";
              ErrHeaders.Add(strError);
              ViewBag.Errors = ErrHeaders;
              return View("MappingErrors");
            }
            switch (item.SurveyContactField)
            {
              case "Title":
                surveyContacts.Title = BespokeFunctions.Proper(responses[Convert.ToInt16(item.ExportOrder) - 1]);
                break;
              case "Forename":
                surveyContacts.Forename = BespokeFunctions.Proper(responses[Convert.ToInt16(item.ExportOrder) - 1]);
                break;
              case "Surname":
                surveyContacts.Surname = BespokeFunctions.Proper(responses[Convert.ToInt16(item.ExportOrder) - 1]);
                break;
              case "Address1":
                surveyContacts.Address1 = BespokeFunctions.Proper(responses[Convert.ToInt16(item.ExportOrder) - 1]);
                break;
              case "TownCity":
                surveyContacts.TownCity = BespokeFunctions.Proper(responses[Convert.ToInt16(item.ExportOrder) - 1]);
                break;
              case "County":
                surveyContacts.County = BespokeFunctions.Proper(responses[Convert.ToInt16(item.ExportOrder) - 1]);
                break;
              case "PostCode":
                surveyContacts.PostCode = responses[Convert.ToInt16(item.ExportOrder) - 1];
                break;
              case "Telephone":
                surveyContacts.Telephone = "0" + responses[Convert.ToInt16(item.ExportOrder) - 1];
                break;
              case "Mobile":
                surveyContacts.Mobile = "0" + responses[Convert.ToInt16(item.ExportOrder) - 1];
                break;
              case "Email":
                surveyContacts.Email = responses[Convert.ToInt16(item.ExportOrder) - 1];
                break;
              case "Country":
                surveyContacts.Country = responses[Convert.ToInt16(item.ExportOrder) - 1];
                break;
              default:
                break;
            }
          }
          surveyContacts.LeadStatus = leadStatus;
          if (surveyContacts.Surname == null || surveyContacts.Surname.Trim().Length == 0)
          {
            ErrHeaders.Add(string.Format("{0} {1}{2}", surveyContacts.Address1, surveyContacts.PostCode, ". Empty Surname in file. Rejected."));
            Dups++;
            headerline = false;
            continue;
          }
          else if (surveyContacts.PostCode == null || surveyContacts.PostCode.Trim().Length == 0 || !BespokeFunctions.ValidatePostcode(surveyContacts.PostCode))
          {
            ErrHeaders.Add(string.Format("{0} {1}{2}", surveyContacts.Forename, surveyContacts.Surname, ". Empty Postcode in file, or Postcode is incorrect format"));
            Dups++;
            headerline = false;
            continue;
          }
          else if (surveyContacts.Address1 == null || surveyContacts.Address1.Trim().Length == 0 || Regex.Matches(surveyContacts.Address1, @"[a-zA-Z]").Count == 0)
          {
            ErrHeaders.Add(string.Format("{0} {1}{2}", surveyContacts.Forename, surveyContacts.Surname, ". Address 1 empty or wrong format."));
            Dups++;
            headerline = false;
            continue;

          }
          else if ((surveyContacts.Telephone == null || surveyContacts.Telephone.Trim().Length == 0) && (surveyContacts.Mobile == null || surveyContacts.Mobile.Trim().Length == 0))
          {
            ErrHeaders.Add(string.Format("{0} {1}{2}", surveyContacts.Forename, surveyContacts.Surname, ". Empty telephone numbers (telephone and mobile both blank) in file. Please remove this row and try again, thank you."));
            Dups++;
            headerline = false;
            continue;
          }
          if (db.PurchaseOrders.
            Where(m => m.CallCentreID == CallCentreID && m.SurveyID == SurveyID).FirstOrDefault().Deficit <= 0)
          {
            return View("PurchaseOrderCompleted");
          }

          if (gr.CheckValidity(SurveyID, string.Format("{0},{1},{2},{3}", surveyContacts.Forename, surveyContacts.Surname, surveyContacts.Telephone, surveyContacts.PostCode)))
          {
            headerline = false;
            Dups++;
            ErrHeaders.Add(string.Format("{0} {1}{2}", surveyContacts.Forename, surveyContacts.Surname, " has been rejected : " + gr.RuleDescription));
            continue;
          }

          // check for duplicates
          if (gr.IsDuplicate(surveyContacts.Title, surveyContacts.Forename, surveyContacts.Surname, surveyContacts.PostCode, surveyContacts.Address1, surveyContacts.Telephone, SurveyID))
          {
            headerline = false;
            Dups++;
            ErrHeaders.Add(string.Format("{0} {1}{2}", surveyContacts.Forename, surveyContacts.Surname, " is a duplicate."));
            continue;
          }



          // check for disallowed
          if (db.ExportDataHistory
            .Any(m => m.Disallow==true && m.datatext.IndexOf(surveyContacts.Forename)>0 && m.datatext.IndexOf(surveyContacts.Surname)>0 && m.datatext.IndexOf(surveyContacts.PostCode)>0))
          {
            headerline = false;
            Dups++;
            ErrHeaders.Add(string.Format("{0} {1}{2}", surveyContacts.Forename, surveyContacts.Surname, " should not be contacted again and is on our disallowed list. You may contact Dunsmore for further information regarding this person."));
            continue;
          }

          // okay, save contact
          db.SurveyContacts.Add(surveyContacts);
          //db.SaveChanges();
          // now to lead the actual survey answers into LeadResults
          List<ExportMappings> listExportMappings = exportMappings.Where(m => m.SurveyMappingsID != null).ToList();
          foreach (var item in listExportMappings)
          {
            LeadResults lr = new LeadResults();
            lr.BlockId = BlockID;
            lr.Question = item.SurveyMapping.LeadStatQuestion.Question;
            lr.LeadStatQuestionsID = item.SurveyMapping.LeadStatQuestionsID;
            lr.Answer = responses[Convert.ToInt16(item.ExportOrder) - 1];
            if (lr.Answer == null || lr.Answer == string.Empty)
            {
              headerline = false;
              ErrHeaders.Add(string.Format("{0} {1}{2}", surveyContacts.Forename, surveyContacts.Surname, " - The Answer is empty but is required as part of the output template. Please ensure it has a value in every import column."));
              Dups++;
              continue;
            }
            if (item.SurveyMapping.MinLength > lr.Answer.Length)
            {
              ErrHeaders.Add(string.Format("{0} {1}{2}", surveyContacts.Forename, surveyContacts.Surname, " - is not long enough. Please check your mappings to investigate further."));
              headerline = false;
              Dups++;
              continue;
            }
            lr.LeadDate = DateTime.Now;
            lr.CallCentreID = CallCentreID;
            db.LeadResults.Add(lr);
          }
          // insert into LeadResults the correct answers that are not in the Export
          foreach (var item in db.SurveyMappings
            .Where(m => m.SurveyID == SurveyID)
            .ToList())
          {
            if (!listExportMappings.Any(m => m.SurveyMappingsID == item.SurveyMappingsID))
            {
              LeadResults lr = new LeadResults();
              lr.BlockId = BlockID;
              lr.Question = item.LeadStatQuestion.Question;
              lr.LeadStatQuestionsID = item.LeadStatQuestionsID;
              lr.Answer = "qualify";
              lr.LeadDate = DateTime.Now;
              lr.CallCentreID = CallCentreID;
              db.LeadResults.Add(lr);
            }
          }
          db.SaveChanges();
          // Survey completion
          SurveyCompletion sc = new SurveyCompletion();
          sc.BlockID = BlockID;
          sc.Agent = "Import_" + db.CallCentres.Find(CallCentreID).CallCentre;
          sc.Note = "Automatic import.";
          sc.DateCompleted = DateTime.Now;
          sc.CallCentreLogon = db.CallCentres.Find(CallCentreID).LogOn;
          db.SurveyCompletion.Add(sc);
          db.SaveChanges();
          TotalUploaded++;
        }
        headerline = false;
      }
      ViewBag.TotalUploaded = TotalUploaded;
      ViewBag.Dups = Dups;

      gr.RunExport(purchaseOrderID);

      return View("SurveyDeployed", ErrHeaders);

    }

    [HttpPost]
    public ContentResult UploadFile()
    {
      var r = new List<ViewDataUploadFilesResult>();

      foreach (string file in Request.Files)
      {
        HttpPostedFileBase hpf = Request.Files[file] as HttpPostedFileBase;
        if (hpf.ContentLength == 0)
          continue;

        string savedFileName = Path.Combine(Server.MapPath("~/MiscFiles"), Path.GetFileName(hpf.FileName));
        hpf.SaveAs(savedFileName); // Save the file

        r.Add(new ViewDataUploadFilesResult()
        {
          Name = hpf.FileName,
          Length = hpf.ContentLength,
          Type = hpf.ContentType
        });

      }
      // Returns json
      return Content("{\"name\":\"" + r[0].Name + "\",\"type\":\"" + r[0].Type + "\",\"size\":\"" + string.Format("{0} bytes", r[0].Length) + "\"}", "application/json");
    }

    [HttpPost]
    public void RegisterFile(int id, string filename)
    {
      LeadResults leadResult = db.LeadResults.Find(id);
      LeadStatus leadStatus = db.LeadStatus.Where(m => m.LeadID == leadResult.LeadID && m.BlockID == leadResult.BlockId).FirstOrDefault();
      leadStatus.VoxFile = filename;
      db.Entry(leadStatus).State = EntityState.Modified;
      db.SaveChanges();
    }

    public ActionResult UploadSurveyData()
    {
      Maintenance.inMaintenance = true;
      int ccID = 0;
      ViewBag.CallCentreID = new SelectList(db.CallCentres.Where(m => m.active == true), "CallCentreID", "CallCentre");
      ViewBag.SurveyID = new SelectList((from s in db.Surveys
                                         join p in db.PurchaseOrders on s.SurveyID equals p.SurveyID
                                         where (ccID == 0 ? p.CallCentreID == p.CallCentreID : p.CallCentreID == ccID) && p.Visible == true
                                         select new { s.SurveyID, s.Ref }).Distinct(), "SurveyID", "Ref");

      return View();
    }

    [HttpPost]
    public ActionResult UploadSurveyData(int SurveyID, int CallCentreID, bool SendPostFile = false)
    {
      PurchaseOrders PO = db.PurchaseOrders.Where(m => m.SurveyID == SurveyID && m.CallCentreID == CallCentreID && m.Visible == true).First();
      GenericRepository gr = new GenericRepository();
      Surveys Survey = db.Surveys.Find(PO.SurveyID);
      gr.RunExport(PO.PurchaseOrderID);
      // is this a Direct Post or a CSV upload
      if ((Survey.HttpPost == null || Survey.HttpPost == false) || SendPostFile == false)
      {
        string newFileName;
        if (Survey.OutputFileName == null)
        {
          newFileName = Survey.Ref + "_" + DateTime.Now.ToString("ddMMyyyy") + ".csv";
        }
        else
        {
          newFileName = Survey.OutputFileName.Replace("ddmmyyyy", DateTime.Now.ToString("ddMMyyyy"));
        }

        List<string> outputLines = db.ExportDataHistory
          .Where(m => m.purchaseorderid == PO.PurchaseOrderID && m.CustomerReceived == null)
          .OrderBy(m => m.exportdataid)
          .Select(m => m.datatext)
          .ToList();
        System.IO.File.WriteAllLines(HttpRuntime.AppDomainAppPath + @"MiscFiles\" + newFileName, outputLines);
        MarkAsSent(PO.PurchaseOrderID);
        return File(HttpRuntime.AppDomainAppPath + @"MiscFiles\" + newFileName, "application/octetstream", newFileName);
      }
      else
      {
        string http_post = Survey.HTTPstring;
        List<string> responseFromClient = new List<string>();
        List<string> dataToSend = db.ExportDataHistory.Where(m => m.purchaseorderid == PO.PurchaseOrderID && m.CustomerReceived == null).Select(m => m.datatext).Distinct().ToList();
        responseFromClient = PostData.PostRequest(http_post, dataToSend);
        @ViewBag.ResponseFromServer = responseFromClient;
        MarkAsSent(PO.PurchaseOrderID);
        return View("UploadComplete");
      }
    }

    private void MarkAsSent(int purchaseOrderID)
    {
      // tag all these records as sent to the Client
      foreach (var item in db.ExportDataHistory.Where(m => m.purchaseorderid == purchaseOrderID && m.CustomerReceived == null))
      {
        item.CustomerReceived = true;
        db.Entry(item).State = EntityState.Modified;
      }
      db.SaveChanges();
    }

    public ActionResult Manage()
    {
      ViewModelData viewModel = new ViewModelData();
      viewModel.CallCentre = db.CallCentres.Where(m => m.active == true).OrderBy(m => m.ccsuffix).FirstOrDefault();
      Maintenance.inMaintenance = true;
      ViewBag.CallCentreID = new SelectList(db.CallCentres.Where(m => m.active == true).OrderBy(m => m.ccsuffix), "callcentreid", "potitle");
      DateTime todaysDate = DateTime.Now;
      viewModel.ListExportDataHistory = db.ExportDataHistory
          .Where(m => m.PurchaseOrder.Visible == true && m.PurchaseOrder.Deficit > 0 && m.PurchaseOrder.CallCentreID == viewModel.CallCentre.CallCentreID)
          .Where(m => EntityFunctions.TruncateTime(m.DateOfExport) == EntityFunctions.TruncateTime(DateTime.Now))
          .ToList();
      return View(viewModel);
    }

    [HttpPost]
    public ActionResult Manage(ViewModelData viewModel, DateTime DateStart, DateTime DateEnd, string forename, string surname, int CallCentreID = 0)
    {
      DateEnd = DateEnd.AddMinutes(1439);

      if (viewModel.ListExportDataHistory != null)
      {
        for (int i = 0; i < viewModel.ListExportDataHistory.Count; i++)
        {
          db.Entry(viewModel.ListExportDataHistory[i]).State = EntityState.Modified;
        }
        db.SaveChanges();
      }
      List<ExportDataHistory> edhs = db.ExportDataHistory.Where(m => m.datatext == null).ToList();
      foreach (var item in edhs)
      {
        db.ExportDataHistory.Remove(item);
      }
      db.SaveChanges();
      viewModel.ListExportDataHistory = db.ExportDataHistory
           .Where(m => m.DateOfExport >= DateStart && m.DateOfExport <= DateEnd)
           .Include(m => m.PurchaseOrder)
           .ToList();
      if (CallCentreID > 0)
      {
        viewModel.ListExportDataHistory = (from v in viewModel.ListExportDataHistory where v.PurchaseOrder.CallCentreID == CallCentreID select v).ToList();
        viewModel.CallCentre = db.CallCentres.Find(CallCentreID);
        ViewBag.CallCentreID = new SelectList(db.CallCentres.Where(m => m.active == true).OrderBy(m => m.ccsuffix), "callcentreid", "potitle", CallCentreID);
      }
      else
      {
        ViewBag.CallCentreID = new SelectList(db.CallCentres.Where(m => m.active == true).OrderBy(m => m.ccsuffix), "callcentreid", "potitle");
      }
      if (forename != null)
      {
        viewModel.ListExportDataHistory = (from v in viewModel.ListExportDataHistory where v.datatext.ToLower().Contains(forename.ToLower()) select v).ToList();
        ViewBag.ForeName = forename;
      }
      if (surname != null)
      {
        viewModel.ListExportDataHistory = (from v in viewModel.ListExportDataHistory where v.datatext.ToLower().Contains(surname.ToLower()) select v).ToList();
        ViewBag.SurName = surname;
      }
      return View(viewModel);
    }

  }
}
